package com.openness.spider;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;

import com.openness.crawler.url.TLDList;
import com.openness.spider.commons.HBaseWritable;
import com.openness.spider.commons.MD5;
import com.openness.spider.commons.Statics;

public class Url implements HBaseWritable {

	private String url = "";

	private String domain = "";

	private String subDomain = "";

	private String path = "";

	private int depth = 0;

	private int priority = 9;

	public Url() {

	}

	public Url(String url) {
		setUrl(url);
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		if (url == null) {
			this.url = "";

			return;
		}

		this.url = url;

		int domainStartIdx = url.indexOf("//") + 2;
		int domainEndIdx = url.indexOf('/', domainStartIdx);
		domain = url.substring(domainStartIdx, domainEndIdx);
		subDomain = "";
		String[] parts = domain.split("\\.");
		if (parts.length > 2) {
			domain = parts[parts.length - 2] + "." + parts[parts.length - 1];
			int limit = 2;
			if (TLDList.getInstance().contains(domain)) {
				domain = parts[parts.length - 3] + "." + domain;
				limit = 3;
			}
			for (int i = 0; i < parts.length - limit; i++) {
				if (subDomain.length() > 0) {
					subDomain += ".";
				}
				subDomain += parts[i];
			}
		}
		path = url.substring(domainEndIdx);
		int pathEndIdx = path.indexOf('?');
		if (pathEndIdx >= 0) {
			path = path.substring(0, pathEndIdx);
		}
	}

	public String getDomain() {
		return domain;
	}

	public void setDomain(String domain) {
		this.domain = domain;
	}

	public String getSubDomain() {
		return subDomain;
	}

	public void setSubDomain(String subDomain) {
		this.subDomain = subDomain;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public int getDepth() {
		return depth;
	}

	public void setDepth(int depth) {
		this.depth = depth;
	}

	public int getPriority() {
		return priority;
	}

	public void setPriority(int priority) {
		this.priority = priority;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (!(obj instanceof Url)) {
			return false;
		}

		Url url = (Url) obj;

		if (this.url.equals(url.url)) {
			return true;
		}

		return false;
	}

	@Override
	public int hashCode() {
		return this.url.hashCode();
	}

	@Override
	public String toString() {
		List<String> strings = new ArrayList<String>();

		strings.add("url: " + url);
		strings.add("domain: " + domain);
		strings.add("subDomain: " + subDomain);
		strings.add("path: " + path);
		strings.add("depth: " + depth);
		strings.add("priority: " + priority);

		return Arrays.toString(strings.toArray(new String[strings.size()]));
	}

	@Override
	public void get(Result result) {
		if (result == null || result.size() == 0) {
			return;
		}

		for (KeyValue kv : result.raw()) {
			if (Bytes.toString(kv.getQualifier()).equalsIgnoreCase("url")) {
				this.url = Bytes.toString(kv.getValue());
			} else if (Bytes.toString(kv.getQualifier()).equalsIgnoreCase(
					"domain")) {
				this.domain = Bytes.toString(kv.getValue());
			} else if (Bytes.toString(kv.getQualifier()).equalsIgnoreCase(
					"subDomain")) {
				this.subDomain = Bytes.toString(kv.getValue());
			} else if (Bytes.toString(kv.getQualifier()).equalsIgnoreCase(
					"path")) {
				this.path = Bytes.toString(kv.getValue());
			} else if (Bytes.toString(kv.getQualifier()).equalsIgnoreCase(
					"depth")) {
				this.depth = Bytes.toInt(kv.getValue());
			} else if (Bytes.toString(kv.getQualifier()).equalsIgnoreCase(
					"priority")) {
				this.priority = Bytes.toInt(kv.getValue());
			}
		}
	}

	@Override
	public Get get() {
		return new Get(Bytes.toBytes(MD5.md5(this.url)));
	}

	@Override
	public Put put() {
		Put put = new Put(Bytes.toBytes(MD5.md5(this.url)));

		put.add(Statics.HBASE_FAMILY, Bytes.toBytes("url"),
				Bytes.toBytes(this.url));
		put.add(Statics.HBASE_FAMILY, Bytes.toBytes("domain"),
				Bytes.toBytes(this.domain));
		put.add(Statics.HBASE_FAMILY, Bytes.toBytes("subDomain"),
				Bytes.toBytes(this.subDomain));
		put.add(Statics.HBASE_FAMILY, Bytes.toBytes("path"),
				Bytes.toBytes(this.path));
		put.add(Statics.HBASE_FAMILY, Bytes.toBytes("depth"),
				Bytes.toBytes(this.depth));
		put.add(Statics.HBASE_FAMILY, Bytes.toBytes("priority"),
				Bytes.toBytes(this.priority));

		return put;
	}

	@Override
	public Delete delete() {
		Delete delete = new Delete(Bytes.toBytes(MD5.md5(this.url)));

		return delete;
	}

}
